package com.sky.common.aspect;

/**
 * ClassName: com.sky.common.aspect
 * Datetime: 2024/10/8 上午9:09
 * Description:
 *
 * @author 汪佳泉
 * @version 1.0
 * @since 1.0
 */

import com.sky.common.annotation.AutoFill;
import com.sky.common.constant.AutoFillConstant;
import com.sky.common.context.BaseContext;
import com.sky.common.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.DispatcherServlet;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 自定义切面，用来实现公共字段自动填充
 */
@Aspect
@Component
@Slf4j
@ConditionalOnClass(DispatcherServlet.class)
public class AutoFillAspect {

    /**
     * 切入点 检测上面有这个注解的方法
     */
    @Pointcut("@annotation(com.sky.common.annotation.AutoFill)")
    public void autoFillPointCut(){}

    /**
     * 前置通知
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        // 记录日志
        log.info("开始进行公共字段的自动填充");
        // 1.先获取注解获取mapper类型
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();// 获取切点方法
        AutoFill annotation = methodSignature.getMethod().getAnnotation(AutoFill.class);// 获取切点上面标注的注解
        OperationType type = annotation.value();// 获取操作类型
        // 2.准备数据
        LocalDateTime time = LocalDateTime.now();
        Long userId = BaseContext.getCurrentId();
        // 3.获取参数 通过反射来为参数赋值
        Object[] args = joinPoint.getArgs(); // 获取待赋值参数
        if(args == null || args.length == 0){
            return;
        }
        Object entity = args[0];
        if(type == OperationType.INSERT){
            // 插入操作，对四个属性进行赋值
            try {
                // 反射获取方法
                Method setCreteTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreteUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                // 反射调用方法
                setCreteTime.invoke(entity,time);
                setCreteUser.invoke(entity,userId);
                setUpdateTime.invoke(entity,time);
                setUpdateUser.invoke(entity,userId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            // 更新操作，对两个属性进行赋值
            try {
                // 反射获取方法
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                // 反射调用方法
                setUpdateTime.invoke(entity,time);
                setUpdateUser.invoke(entity,userId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }



}
